package com.gitee.wsl.struct.grammar.parser.context.ext

import com.gitee.wsl.struct.grammar.parser.Parser
import com.gitee.wsl.struct.grammar.parser.ParsingScope
import com.gitee.wsl.struct.grammar.parser.combinator.poll


suspend inline fun <T : Any, S : Any> ParsingScope.reduce(
    term: Parser<T>,
    operator: Parser<S>,
    transform: (T, S, T) -> T
): T {
    var l: T = term()
    while (true) {
        val o = poll(operator) ?: break
        val r = term()
        l = transform(l, o, r)
    }
    return l
}

suspend inline fun <T : Any, S : Any> ParsingScope.reduceRight(
    term: Parser<T>,
    operator: Parser<S>,
    transform: (T, S, T) -> T
): T {
    val stack = mutableListOf<Pair<T, S>>()
    var t = term()
    while (true) {
        val o = poll(operator) ?: break
        stack += t to o
        t = term()
    }

    for ((l, o) in stack.asReversed()) {
        t = transform(l, o, t)
    }
    return t
}